package com.javawork.juc.two;

import java.util.concurrent.TimeUnit;

/**
 * @author zhangxiaolu
 * @date 2023-02-06 19:05
 */
public class Lock8Demo {

    /**
     * 8锁案例
     * 1.标准访问有ab两个线程，请问先打印邮件还是短信
     * 2.sendEmail()方法中赞同3秒，请问先打印邮件还是短信
     * 3.添加一个普通的hello(),请问先打印邮件还是hello
     * 4.有两部手机，请问先打印邮件还是短信
     * 5.有两个静态同步方法，一部手机，请问先打印邮件还是短信
     * 6.有两个静态同步方法，2部手机，请问先打印邮件还是短信
     * 7.有1个静态同步方法，一个普通的同步方法，一部手机，请问先打印邮件还是短信
     * 8.有1个静态同步方法，一个普通的同步方法，2部手机，请问先打印邮件还是短信
     *
     * 笔记总结：
     * 1-2
     * 一个对象里面如果有多个Synchronized方法，某一时刻，只要有一个线程去调用其中的一个synchronized方法了
     * 其他线程都只能等待，换句话说，某一时刻内，只能有唯一的一个线程去访问这些synchronized方法，锁的是当前对
     * 象this，被锁定后，其他的线程都不能进入到当前对象的其他synchronizaed方法。
     * 3-4
     * 加个普通方法后发现和同步锁无关
     * 换成两个对象后，不是同一把锁了，情况立刻变化
     * 5-6
     * 三种synchronized锁的内容有一些差别：
     * 对于普通方法，锁的是当前实例对象，通常指this，具体的一部手机，所有的普通同步方法用的都是同一把锁->实例对象本身
     * 对于同步方法块，锁的是synchronized括号内的对象
     * 7-8
     * 当一个线程试图访问同步代码时它必须先得到锁，正常退出或抛出异常时必须释放锁
     * 所有的普通同步方法用的都是同一把锁——实例对象本身，就是new出来的具体实例对象本身，本类this
     * 也就是说如果一个实例对象的普通同步方法获取锁后，该实例对象的其他普通同步方法必须等待获取锁的方法释放锁后才能重新获取
     *
     * 所有的静态同步方法用的也是同一把锁，类对象本身，就是我们说的唯一模板class
     * 具体实例对象this和唯一模板class，这两把锁是两个不同的对象，所以静态同步方法与普通同步方法之间是不会有竟态条件的
     * 但是一旦一个静态同步方法获取锁后，其他的静态同步方法都必须等待该方法释放锁后才能获取锁
     */
    public static void main(String[] args) {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(() -> {
            phone.sendEmail();
        }, "a").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
//            phone.sendSMS();
            phone2.sendSMS();
//            phone.hello();
        }, "b").start();
    }
}

class Phone{

    public synchronized void sendEmail() {
        System.out.println("---------sendEmail");
    }

    public synchronized void sendSMS() {
        System.out.println("---------sendSMS");
    }

    public void hello() {
        System.out.println("hello world");
    }
}